﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq.Expressions;

namespace MyBasicLib.Data.ORMLiteNew
{ 
    /// <summary>
    /// 数据查询
    /// </summary>
    public interface IDbQueryable
    {
        //IDataContext DataContext { get; }
        IDbQueryProvider DbProvider { get; }
        IList<DbExpression> DbExpressions { get; }
    }

    public interface IDbQueryable<TElement> : IDbQueryable //: System.Linq.IQueryable<TSource>
    {
        //TElement Execute();

        //List<TElement> ExecuteList();
    }
    /// <summary>
    /// 用于翻译IDbQueryable并执行
    /// </summary>
    public interface IDbQueryProvider
    {
       // string GenerateSql(IDbQueryable queryable, out IList<object> parameterValues, out CommandType commandType);

        IList<TElement> ExecuteList<TElement>(IDbQueryable queryable);
        TElement Execute<TElement>(IDbQueryable queryable); 
        int SubmitChanges(IList<IDbQueryable> queryable);  
    }

    public sealed class ProviderCapacity
    { 
    }

    #region DbExpression
    public enum DbExpressionType
    {
        None,
        Source,
        All,
        Any,
        Average,
        Count,
        DefaultIfEmpty,
        Distinct,
        First,
        FirstOrDefault,
        GroupBy,
        GroupJoin,
        Join,
        Max,
        Min,
        OrderBy,
        OrderByDescending,
        Select,
        SelectMany,
        Single,
        SingleOrDefault,
        Skip,
        Sum,
        Take,
        ThenBy,
        ThenByDescending,
        Where,
        Union,
        Insert,
        Delete,
        Update
    }
    public abstract class DbExpression
    {
        protected DbExpression(DbExpressionType dbExpressionType)
        {
            DbExpressionType = dbExpressionType;
        }

        public DbExpressionType DbExpressionType { get; set; }
    }

    public interface IKeySelectorExpression
    {
        Expression KeySelector { get; set; }
    }

    public class SourceDbExpression : DbExpression
    {
        public SourceDbExpression(IDbQueryable query)
            : base(DbExpressionType.Source)
        {
            Query = query;
            SourceType = query.GetType().GetGenericArguments()[0];
        }

        public IDbQueryable Query { get; set; }
        public Type SourceType { get; set; }
    }

    public class DistinctDbExpression : DbExpression
    {
        public DistinctDbExpression()
            : base(DbExpressionType.Distinct)
        {
        }
    }
    public class UnionDbExpression : DbExpression
    {
        public IList<IDbQueryable> Querys { get; set; } 

        public UnionDbExpression()
            : base(DbExpressionType.Union)
        {
        }
    }


    public class DefaultIfEmptyDbExpression : DbExpression
    {
        public DefaultIfEmptyDbExpression()
            : base(DbExpressionType.DefaultIfEmpty)
        {
        }
    }

    public class AllDbExpression : DbExpression
    {
        public AllDbExpression(Expression predicate)
            : base(DbExpressionType.All)
        {
            Predicate = predicate;
        }

        public Expression Predicate { get; set; }
    }

    public class AnyDbExpression : DbExpression
    {
        public AnyDbExpression(Expression predicate)
            : base(DbExpressionType.Any)
        {
            Predicate = predicate;
        }

        public Expression Predicate { get; set; }
    }

    public class CountDbExpression : DbExpression
    {
        public CountDbExpression(Expression predicate)
            : base(DbExpressionType.Count)
        {
            Predicate = predicate;
        }

        public Expression Predicate { get; set; }
    }

    public class FirstDbExpression : DbExpression
    {
        public FirstDbExpression(Expression predicate)
            : base(DbExpressionType.First)
        {
            Predicate = predicate;
        }

        public Expression Predicate { get; set; }
    }

    public class SingleDbExpression : DbExpression
    {
        public SingleDbExpression(Expression predicate)
            : base(DbExpressionType.Single)
        {
            Predicate = predicate;
        }

        public Expression Predicate { get; set; }
    }

    public class WhereDbExpression : DbExpression
    {
        public WhereDbExpression(Expression predicate)
            : base(DbExpressionType.Where)
        {
            Predicate = predicate;
        }

        public Expression Predicate { get; set; }
    }

    public class OrderByDbExpression : DbExpression, IKeySelectorExpression
    {
        public OrderByDbExpression(Expression keySelector)
            : base(DbExpressionType.OrderBy)
        {
            KeySelector = keySelector;
        }

        #region IKeySelectorExpression Members

        public Expression KeySelector { get; set; }

        #endregion
    }

    public class OrderByDescendingDbExpression : DbExpression, IKeySelectorExpression
    {
        public OrderByDescendingDbExpression(Expression keySelector)
            : base(DbExpressionType.OrderByDescending)
        {
            KeySelector = keySelector;
        }

        #region IKeySelectorExpression Members

        public Expression KeySelector { get; set; }

        #endregion
    }

    public class ThenByDbExpression : DbExpression, IKeySelectorExpression
    {
        public ThenByDbExpression(Expression keySelector)
            : base(DbExpressionType.ThenBy)
        {
            KeySelector = keySelector;
        }

        #region IKeySelectorExpression Members

        public Expression KeySelector { get; set; }

        #endregion
    }

    public class ThenByDescendingDbExpression : DbExpression, IKeySelectorExpression
    {
        public ThenByDescendingDbExpression(Expression keySelector)
            : base(DbExpressionType.ThenByDescending)
        {
            KeySelector = keySelector;
        }

        #region IKeySelectorExpression Members

        public Expression KeySelector { get; set; }

        #endregion
    }

    public class SelectDbExpression : DbExpression
    {
        public SelectDbExpression(Expression selector)
            : base(DbExpressionType.Select)
        {
            Selector = selector;
        }

        public Expression Selector { get; set; }
    }

    public class SelectManyDbExpression : DbExpression
    {
        public SelectManyDbExpression(Expression selector)
            : base(DbExpressionType.SelectMany)
        {
            Selector = selector;
        }

        public Expression Selector { get; set; }
    }

    public class SkipDbExpression : DbExpression
    {
        public SkipDbExpression(int count)
            : base(DbExpressionType.Skip)
        {
            Count = count;
        }

        public int Count { get; set; }
    }

    public class TakeDbExpression : DbExpression
    {
        public TakeDbExpression(int count)
            : base(DbExpressionType.Take)
        {
            Count = count;
        }

        public int Count { get; set; }
    }

    public enum JoinType
    {
        InnerJoin,
        LeftJoin,
        CrossJoin
    }
     
    public class JoinDbExpression : DbExpression
    {
        public JoinDbExpression()
            : base(DbExpressionType.Join)
        {
            JoinType = JoinType.InnerJoin;
        }

        public IDbQueryable Inner { get; set; }

        public Expression InnerKeySelector { get; set; }

        public Expression OuterKeySelector { get; set; }

        public Expression ResultSelector { get; set; }
        public JoinType JoinType { get; set; }
    }

    public class GroupJoinDbExpression : JoinDbExpression
    {
        public GroupJoinDbExpression()
        {
            base.DbExpressionType = DbExpressionType.GroupJoin;
        }
    }

    public enum ModifyFrom
    {
        Entity,
        Query
    }

    public class InsertDbExpression : DbExpression
    {
        public InsertDbExpression(object entity)
            : base(DbExpressionType.Insert)
        {
            ModifyFrom = ModifyFrom.Entity;
            Entity = entity;
        }

        public InsertDbExpression()
            : base(DbExpressionType.Insert)
        {
            ModifyFrom = ModifyFrom.Query;
        }

        public object Entity { get; set; }
        public ModifyFrom ModifyFrom { get; set; }
    }

    public class UpdateDbExpression : DbExpression
    {
        public UpdateDbExpression(object entity)
            : base(DbExpressionType.Update)
        {
            ModifyFrom = ModifyFrom.Entity;
            Entity = entity;
        }

        public UpdateDbExpression(Expression expression)
            : base(DbExpressionType.Update)
        {
            ModifyFrom = ModifyFrom.Query;
            UpdateExpression = expression;
        }

        public object Entity { get; set; }
        public Expression UpdateExpression { get; set; }
        public ModifyFrom ModifyFrom { get; set; }
    }

    public class DeleteDbExpression : DbExpression
    {
        public DeleteDbExpression()
            : base(DbExpressionType.Delete)
        {
        }
    }

    #endregion
}